package com.kinyx.framework.processor;

import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;

public abstract class Processor extends AbstractProcessor {

	protected Context context;

	@Override
	public synchronized void init(final ProcessingEnvironment processingEnvironment) {
		super.init(processingEnvironment);
		this.context = new Context(processingEnvironment);
	}

	@Override
	public SourceVersion getSupportedSourceVersion() {
		return SourceVersion.latestSupported();
	}

	@Override
	public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnvironment) {
		if (roundEnvironment.processingOver()) {
			this.context.getLogger().NOTE("Processor.process -> RoundEnvironment.processingOver() == true");
			return false;
		} else {
			this.context.getLogger().NOTE("Processor.process -> RoundEnvironment.processingOver() == false");
		}
		if (annotations.isEmpty()) {
			this.context.getLogger().NOTE("Processor.process -> Set<? extends TypeElement>.isEmpty() == true");
			return false;
		} else {
			this.context.getLogger().NOTE("Processor.process -> Set<? extends TypeElement>.isEmpty() == false");
			for (final TypeElement annotation : annotations) {
				this.context.getLogger().NOTE("Processor.process -> annotation[" + annotation.getQualifiedName() + "]");
			}
		}

		try {
			this.context.getLogger().NOTE("Processor.process -> started");
			this.doProcess(annotations, roundEnvironment);
		} catch (final Exception e) {
			this.context.getLogger().ERROR("Processor.process -> throws Exception[" + e.getMessage() + "]");
			e.printStackTrace();
			return true;
		}

		this.context.getLogger().NOTE("Processor.process -> finished");
		return false;
	}

	protected abstract void doProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment);

}
